package se.thoka.twt.client.utils;

import com.google.gwt.core.client.GWT;
import com.google.gwt.i18n.client.DateTimeFormat;

public class I18N {
	
	private static I18NHandler handler;

	/**
	 * @return The date format.
	 */
	public static DateTimeFormat getDateFormat() {
		return getHandler().getDateFormat();
	}

	/**
	 * @return The time format.
	 */
	public static DateTimeFormat getTimeFormat() {
		return getHandler().getTimeFormat();
	}

	/**
	 * @return The date & time format.
	 */
	public static DateTimeFormat getDateTimeFormat() {
		return getHandler().getDateTimeFormat();
	}

	/**
	 * Returns the month name of the supplied date
	 * 
	 * @param date The date
	 * @return The month name
	 */
	public static String getMonthName(GWTDate date) {
		return getMonthName(date.getMonthOfYear() - 1);
	}
	
	/**
	 * Returns the month name of the supplied month offset
	 * 
	 * @param monthOffset The month offset, where <code>1</code> is January
	 * @return The month name
	 */
	public static String getMonthName(int monthOffset) {
		return getHandler().getMonthName(monthOffset);
	}

	/**
	 * Returns the short month name of the supplied date
	 * 
	 * @param date The date
	 * @return The short month name
	 */
	public static String getMonthShortName(GWTDate date) {
		return getMonthShortName(date.getMonthOfYear() - 1);
	}
	
	/**
	 * Returns the short month name of the supplied month offset
	 * 
	 * @param monthOffset The month offset, where <code>1</code> is January
	 * @return The short month name
	 */
	public static String getMonthShortName(int monthOffset) {
		return getHandler().getMonthShortName(monthOffset);
	}

	/**
	 * Returns the week day name of the supplied date
	 * 
	 * @param date The date
	 * @return The week day name
	 */
	public static String getWeekDayName(GWTDate date) {
		return getWeekDayName(new DateTimeUtil(date.toDate()).getDayOfWeek());
	}
	
	/**
	 * Returns the week day name of the supplied day offset
	 * 
	 * @param dayOffset The day offset, where <code>0</code> is Sunday
	 * @return The week day name
	 */
	public static String getWeekDayName(int dayOffset) {
		return getHandler().getWeekDayName(dayOffset);
	}

	/**
	 * Returns the short week day name of the supplied date
	 * 
	 * @param date The date
	 * @return The short week day name
	 */
	public static String getWeekDayShortName(GWTDate date) {
		return getWeekDayShortName(new DateTimeUtil(date.toDate()).getDayOfWeek());
	}
	
	/**
	 * Returns the short week day name of the supplied day offset
	 * 
	 * @param dayOffset The day offset, where <code>0</code> is Sunday
	 * @return The short week day name
	 */
	public static String getWeekDayShortName(int dayOffset) {
		return getHandler().getWeekDayShortName(dayOffset);
	}

	/**
	 * Returns the week day initial of the supplied date
	 * 
	 * @param date The date
	 * @return The week day initial
	 */
	public static String getWeekDayInitial(GWTDate date) {
		return getWeekDayInitial(new DateTimeUtil(date.toDate()).getDayOfWeek());
	}

	/**
	 * Returns the week day initial of the supplied day offset
	 * 
	 * @param dayOffset The day offset, where <code>0</code> is Sunday
	 * @return The week day initial
	 */
	public static String getWeekDayInitial(int dayOffset) {
		return getHandler().getWeekDayInitial(dayOffset);
	}
	
	/**
	 * @return The week initial, e.g. "w" for "week"
	 */
	public static String getWeekInitial() {
		return getHandler().getWeekInitial();
	}
	
	/**
	 * @return The translation of "Today"
	 */
	public static String getTodayTranslation() {
		return getHandler().getTodayTranslation();
	}
	
	/**
	 * @return The translation of "Tomorrow"
	 */
	public static String getTomorrowTranslation() {
		return getHandler().getTomorrowTranslation();
	}
	
	/**
	 * @return The translation of "Yesterday"
	 */
	public static String getYesterdayTranslation() {
		return getHandler().getYesterdayTranslation();
	}

	/**
	 * @return The start of week where <code>0</code> is Sunday
	 */
	public static int getStartOfWeek() {
		return getHandler().getStartOfWeek();
	}

	/**
	 * Formats a date with {@link I18N#getDateFormat()}
	 * 
	 * @param date The date
	 * @return Formatted date
	 */
	public static String formatDate(GWTDate date) {
		return date != null ? getDateFormat().format(date.toDate()) : null;
	}

	/**
	 * Formats a date time with {@link I18N#getDateTimeFormat()}
	 * 
	 * @param dateTime The date and time
	 * @return Formatted date and time
	 */
	public static String formatDateTime(GWTDateTime dateTime) {
		return dateTime != null ? getDateTimeFormat().format(dateTime.toDate()) : null;
	}

	/**
	 * Formats a time with {@link I18N#getTimeFormat()}
	 * 
	 * @param time The time
	 * @return Formatted time
	 */
	public static String formatTime(GWTTime time) {
		return time != null ? getTimeFormat().format(new GWTDateTime(new GWTDate(), time).toDate()) : null;
	}

	/**
	 * Tries to parse a date string into a {@link GWTDate}
	 * 
	 * @param dateString The date string
	 * @return A date or <code>null</code> if parsing fails
	 */
	public static GWTDate tryParseDate(String dateString) {
		GWTDate result;
		try {
			result = new GWTDate(getDateFormat().parseStrict(dateString));
			
		} catch (Exception e) {
			result = null;
		}

		return result;
	}

	/**
	 * Tries to parse a date time string into a {@link GWTDateTime}
	 * 
	 * @param dateTimeString The date time string
	 * @return A date time or <code>null</code> if parsing fails
	 */
	public static GWTDateTime tryParseDateTime(String dateTimeString) {
		GWTDateTime result;
		try {
			result = new GWTDateTime(getDateTimeFormat().parseStrict(dateTimeString));
		} catch (Exception e) {
			result = null;
		}

		return result;
	}

	/**
	 * Tries to parse a time string into a {@link GWTTime}
	 * 
	 * @param timeString The time string
	 * @return A time or <code>null</code> if parsing fails
	 */
	public static GWTTime tryParseTime(String timeString) {
		GWTTime result;
		try {
			result = new GWTTime(getTimeFormat().parseStrict(timeString));
		} catch (Exception e) {
			result = null;
		}

		return result;
	}
	
	/**
	 * Touches this class to allow pre-initiation.
	 * @param runTest Set <code>true</code> to run a test and to log it.
	 */
	public static void touch(boolean runTest) {
		getHandler();
	}
	
	private static I18NHandler getHandler() {
		if (handler == null) {
			handler = GWT.create(I18NHandler.class);
			TWTLogger.log("I18N handler created " + handler.getClass().getName());
		}
		
		return handler;
	}
}
